package com.example.utils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 缓存工具类，用于与Redis进行交互，实现数据的存取和删除操作。
 */
@Component
public class CacheUtils {
    @Resource
    StringRedisTemplate template;

    /**
     * 从缓存中取出指定键的数据并转换为指定类型。
     *
     * @param key      缓存键
     * @param dataType 数据类型Class对象
     * @return 转换后的数据对象，若缓存中无数据则返回null
     */
    public <T> T takeFromCache(String key, Class<T> dataType) {
        String s = template.opsForValue().get(key);
        if (s == null) return null;
        return JSONObject.parseObject(s).to(dataType);
    }

    /**
     * 从缓存中取出指定键的列表数据并转换为指定类型的列表。
     *
     * @param key      缓存键
     * @param itemType 列表项的数据类型Class对象
     * @return 转换后的列表，若缓存中无数据则返回null
     */
    public <T> List<T> takeListFromCache(String key, Class<T> itemType) {
        String s = template.opsForValue().get(key);
        if (s == null) return null;
        return JSONArray.parseArray(s).toList(itemType);
    }

    /**
     * 将数据对象保存到缓存中，并设置过期时间。
     *
     * @param key    缓存键
     * @param data   数据对象
     * @param expire 过期时间（秒）
     */
    public <T> void saveToCache(String key, T data, long expire) {
        template.opsForValue().set(key, JSONObject.from(data).toJSONString(), expire, TimeUnit.SECONDS);
    }

    /**
     * 将列表数据保存到缓存中，并设置过期时间。
     *
     * @param key    缓存键
     * @param list   数据列表
     * @param expire 过期时间（秒）
     */
    public <T> void saveListToCache(String key, List<T> list, long expire) {
        template.opsForValue().set(key, JSONArray.from(list).toJSONString(), expire, TimeUnit.SECONDS);
    }

    /**
     * 根据指定键模式删除缓存中的所有匹配项。
     *
     * @param key 键模式
     */
    public void deleteCachePattern(String key) {
        Set<String> keys = Optional.ofNullable(template.keys(key)).orElse(Collections.emptySet());
        template.delete(keys);
    }

    /**
     * 删除缓存中指定键的数据。
     *
     * @param key 缓存键
     */
    public void deleteCache(String key) {
        template.delete(key);
    }
}
